#ifndef DATAMEMORYORGANISATION_HPP
#define DATAMEMORYORGANISATION_HPP

#include <QObject>

#include "bank.hpp"
#include "ioregister.hpp"
#include "register.hpp"

/**
* @brief
*
* @class DataMemoryOrganisation datamemoryorganisation.hpp "datamemoryorganisation.hpp"
*/
class DataMemoryOrganisation : public QObject
{
Q_OBJECT
public:
    /**
    * @brief
    *
    * @fn DataMemoryOrganisation
    * @param parent
    */
    explicit DataMemoryOrganisation(QObject *parent = 0);

    /**
    * @brief Switches the bank between 0 and 1
    *
    * @fn switchBank
    */
    void switchBank();

    /**
    * @brief Switches the bank to the given one
    * @details false = bank0, true = 1
    *
    * @fn switchBank
    * @param bank
    */
    void switchBank(bool bank);

    /**
    * @brief Returns the actual bank
    *
    * @fn getActualBank
    * @return Bank
    */
    Bank *getActualBank();

    /**
    * @brief Returns the register for PortA
    *
    * @fn getPortA
    * @return IORegister
    */
    IORegister *getPortA();

    /**
    * @brief Returns the register for PortB
    *
    * @fn getPortB
    * @return IORegister
    */
    IORegister *getPortB();

    /**
    * @brief Return the working Register
    *
    * @fn getWorkingRegister
    * @return Register
    */
    Register *getWorkingRegister();

    Register *getPrescaler();

    Register *getRegister(int address);

    void reset();

    void resetNormalOperation();

private:
    /**
    * @brief Indicates the actual bank
    * @details false = bank0, true = bank1
    *
    * @var actualBank
    */
    bool actualBank;
    Bank *bank0;
    Bank *bank1;
    IORegister *portA;
    IORegister *portB;
    Register *workingRegister;
    Register *prescaler;

    /**
    * @brief Initiates the registers for bank0 and bank1
    *
    * @fn initRegister
    */
    void initRegister();

signals:

    /**
    * @brief Emitted when bank switches
    *
    * @fn switchBank
    */
    void switchBankSignal(bool bank);

    /**
    * @brief Emitted when register changes
    *
    * @fn registerChanged
    * @param reg
    */
    void registerChanged(Register *reg);

public slots:
    void onRegisterChanged(int address, int bank);
    void onRequestChangeRegister(int address, int value);
    void onRequestSwitchBank(bool bank);

};

#endif // DATAMEMORYORGANISATION_HPP
